/**
 * Copyright 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule findDOMNode
 */

'use strict'

var ReactCurrentOwner = require('./ReactCurrentOwner')
var ReactDOMComponentTree = require('./ReactDOMComponentTree')
var ReactInstanceMap = require('./ReactInstanceMap')

var getNativeComponentFromComposite = require('./getNativeComponentFromComposite')
var invariant = require('fbjs/lib/invariant')
var warning = require('fbjs/lib/warning')

/**
 * Returns the DOM node rendered by this element.
 *
 * @param {ReactComponent|DOMElement} componentOrElement
 * @return {?DOMElement} The root node of this element.
 */
function findDOMNode(componentOrElement) {
  if (process.env.NODE_ENV !== 'production') {
    var owner = ReactCurrentOwner.current
    if (owner !== null) {
      process.env.NODE_ENV !== 'production'
        ? warning(
            owner._warnedAboutRefsInRender,
            '%s is accessing findDOMNode inside its render(). ' +
              'render() should be a pure function of props and state. It should ' +
              'never access something that requires stale data from the previous ' +
              'render, such as refs. Move this logic to componentDidMount and ' +
              'componentDidUpdate instead.',
            owner.getName() || 'A component'
          )
        : void 0
      owner._warnedAboutRefsInRender = true
    }
  }
  if (componentOrElement == null) {
    return null
  }
  if (componentOrElement.nodeType === 1) {
    return componentOrElement
  }

  var inst = ReactInstanceMap.get(componentOrElement)
  if (inst) {
    inst = getNativeComponentFromComposite(inst)
    return inst ? ReactDOMComponentTree.getNodeFromInstance(inst) : null
  }

  if (typeof componentOrElement.render === 'function') {
    !false
      ? process.env.NODE_ENV !== 'production'
        ? invariant(false, 'findDOMNode was called on an unmounted component.')
        : invariant(false)
      : void 0
  } else {
    !false
      ? process.env.NODE_ENV !== 'production'
        ? invariant(
            false,
            'Element appears to be neither ReactComponent nor DOMNode (keys: %s)',
            Object.keys(componentOrElement)
          )
        : invariant(false)
      : void 0
  }
}

module.exports = findDOMNode
